package com.zlc.workflow.core.instance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zlc.common.core.process.model.entity.StoneProcessLog;
import com.zlc.common.core.process.model.vo.StoneProcessLogVo;
import com.zlc.common.core.process.service.StoneProcessLogService;
import com.zlc.common.util.BeanCopyUtils;
import com.zlc.workflow.constant.ProcessLogTypeEnum;
import com.zlc.workflow.core.instance.cmd.BuildWorkflowCmd;
import com.zlc.workflow.core.instance.cmd.NextTaskNodeCmd;
import com.zlc.workflow.core.instance.cmd.NotifyNodeCmd;
import com.zlc.workflow.core.instance.cmd.QueryRejectNodeCmd;
import com.zlc.workflow.core.instance.cmd.QueryWorkflowDetailCmd;
import com.zlc.workflow.core.instance.cmd.RejectCmd;
import com.zlc.workflow.core.instance.cmd.SubmitCmd;
import com.zlc.workflow.core.instance.cmd.TerminationCmd;
import com.zlc.workflow.core.instance.model.BuildFlowParam;
import com.zlc.workflow.core.instance.model.NotifyWaitNodeParam;
import com.zlc.workflow.core.instance.model.QueryFlowDetailParam;
import com.zlc.workflow.core.instance.model.QueryNextTaskParam;
import com.zlc.workflow.core.instance.model.QueryRejectNodeParam;
import com.zlc.workflow.core.instance.model.RejectFlowParam;
import com.zlc.workflow.core.instance.model.RejectNodeVo;
import com.zlc.workflow.core.instance.model.SubmitFlowParam;
import com.zlc.workflow.core.instance.model.TerminationFlowParam;
import com.zlc.workflow.core.instance.model.WorkflowDetail;
import com.zlc.workflow.core.instance.model.WorkflowTaskNode;
import com.zlc.workflow.core.instance.service.InstanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Collections;
import java.util.List;

@Service
@Transactional(rollbackFor = Exception.class)
public class InstanceServiceImpl implements InstanceService {

    @Autowired
    private QueryWorkflowDetailCmd queryWorkflowDetailCmd;
    @Autowired
    private StoneProcessLogService stoneProcessLogService;

    @Override
    public WorkflowDetail workflowDetail(QueryFlowDetailParam param) {
        return queryWorkflowDetailCmd.getWorkflowDetail(param);
    }

    @Override
    public WorkflowTaskNode nextTask(QueryNextTaskParam param) {
        return new NextTaskNodeCmd(param).execute();
    }

    @Override
    public WorkflowDetail buildFLow(BuildFlowParam param) {
        return new BuildWorkflowCmd(param).execute();
    }

    @Override
    public WorkflowDetail buildAndSubmit(SubmitFlowParam param) {
        BuildFlowParam buildFlowParam = BeanCopyUtils.copyObj(param,BuildFlowParam.class);
        WorkflowDetail detail = buildFLow(buildFlowParam);
        param.setProcessInstanceId(detail.getProcessInstanceId());
        param.setTaskId(detail.getDetails().getTaskId());
        return submit(param);
    }

    @Override
    public WorkflowDetail submit(SubmitFlowParam param) {
        return new SubmitCmd(param).execute();
    }

    @Override
    public List<RejectNodeVo> getRejectNodeList(QueryRejectNodeParam param) {
        return new QueryRejectNodeCmd(param).execute();
    }

    @Override
    public WorkflowDetail reject(RejectFlowParam param) {
        return new RejectCmd(param).execute();
    }

    @Override
    public WorkflowDetail termination(TerminationFlowParam param) {
        return new TerminationCmd(param).execute();
    }

    @Override
    public WorkflowDetail notifyWaitNode(NotifyWaitNodeParam param) {
        return new NotifyNodeCmd(param).execute();
    }

    @Override
    public List<StoneProcessLogVo> queryProcessLog(String processInstanceId) {
        LambdaQueryWrapper<StoneProcessLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoneProcessLog::getProcessInstanceId,processInstanceId);
        wrapper.orderByAsc(StoneProcessLog::getCreateTime);
        List<StoneProcessLogVo> stoneProcessLogVos = stoneProcessLogService.queryVoList(wrapper);
        stoneProcessLogVos.forEach(log->{
            String operateUser = log.getOperateUser();
            if(!ObjectUtils.isEmpty(operateUser)){
                String[] split = operateUser.split(";");
                if(split.length > 1){
                    log.setOperateUserName(split[1]);
                }
            }
            if(!ObjectUtils.isEmpty(log.getOperateType())){
                ProcessLogTypeEnum logType = ProcessLogTypeEnum.getLogType(log.getOperateType());
                if(!ObjectUtils.isEmpty(logType)){
                    log.setOperateTypeName(logType.getDesc());
                }
            }
        });
        return stoneProcessLogVos;
    }
}
